/*
 * $Id: time.c,v 1.33 2006-02-07 07:42:54 bacon Exp $
 */

#include <xp/bas/time.h>
#include <xp/bas/errno.h>

#ifdef _WIN32
	#define WIN_EPOCH_YEAR  ((xp_time_t)1601)
	#define WIN_EPOCH_MON   ((xp_time_t)1)
	#define WIN_EPOCH_DAY   ((xp_time_t)1)

	#define EPOCH_DIFF_YEARS (XP_EPOCH_YEAR - WIN_EPOCH_YEAR)
	#define EPOCH_DIFF_DAYS (EPOCH_DIFF_YEARS * 365 + EPOCH_DIFF_YEARS / 4 - 3)
	#define EPOCH_DIFF_SECS (EPOCH_DIFF_DAYS * 24 * 60 * 60)
	#define EPOCH_DIFF_MSECS (EPOCH_DIFF_SECS * XP_MSEC_IN_SEC)
#endif

/*
#ifdef __linux
	#include <linux/unistd.h>

	static inline _syscall2 (int, gettimeofday,
		xp_timeval_t*, tv, xp_timezone_t*, tz);
	static inline _syscall2 (int, settimeofday, 
		const xp_timeval_t*, tv, const xp_timezone_t*, tz);
#endif
*/

int xp_gettime (xp_time_t* value)
{
#ifdef _WIN32
	SYSTEMTIME st;
	FILETIME ft;

	/* 
	 * MSDN: The FILETIME structure is a 64-bit value representing the 
	 *       number of 100-nanosecond intervals since January 1, 1601 (UTC).
	 */

	GetSystemTime (&st);
	if (SystemTimeToFileTime (&st, &ft) == FALSE) return -1;
	*value = ((xp_time_t)(*((xp_int64_t*)&ft)) / (10 * 1000));
	*value -= EPOCH_DIFF_MSECS;
	return 0;
#else
	xp_timeval_t tv;
	if (gettimeofday (&tv, XP_NULL) == -1) return -1;
	*value = XP_TIMEVAL_TO_TIME (tv);
	return 0;
#endif
}

int xp_settime (xp_time_t value)
{
#ifdef _WIN32
	FILETIME ft;
	SYSTEMTIME st;

	*((xp_int64_t*)&ft) = ((value + EPOCH_DIFF_MSECS) * (10 * 1000));
	if (FileTimeToSystemTime (&ft, &st) == FALSE) return -1;
	if (SetSystemTime(&st) == FALSE) return -1;
	return 0;
#else
	xp_timeval_t tv;
	XP_TIME_TO_TIMEVAL (value, &tv);
	if (settimeofday (&tv, XP_NULL) == -1) return -1;
	return 0;
#endif
}

